package com.bnzj.core.export;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.function.Function;

import com.bnzj.core.util.FbConstant;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.ClientAnchor;

import com.bnzj.core.util.DateUtils;
import com.bnzj.core.util.BeanConvertUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * @author barry
 * @date 2019-10-10
 */
@Slf4j
public class ExportUtils {

    /**
     * 用于单Sheet导出
     * @param title
     * @param dataList
     * @param columns
     * @param dir
     * @return
     */
    public static String exportExcel(String title, List<?> dataList, List<Column> columns, String dir) {
        try (HSSFWorkbook workbook = new HSSFWorkbook()) {
            // 声明一个工作薄
            // 生成一个表格
            HSSFSheet sheet = workbook.createSheet(title);
            // 设置表格默认列宽度为15个字节
            sheet.setDefaultColumnWidth(20);
            // 生成一个样式
            HSSFCellStyle style = workbook.createCellStyle();
            // 生成一个字体
            HSSFFont font = workbook.createFont();

            font.setFontHeightInPoints((short)12);
            font.setBold(true);
            // 把字体应用到当前的样式
            style.setFont(font);
            // 生成并设置另一个样式
            HSSFCellStyle style2 = workbook.createCellStyle();
            // 生成另一个字体
            HSSFFont font2 = workbook.createFont();
            font2.setBold(false);
            // 把字体应用到当前的样式
            style2.setFont(font2);
            HSSFFont font3 = workbook.createFont();
            // 声明一个画图的顶级管理器
            HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
            // 产生表格标题行
            HSSFRow row = sheet.createRow(0);
            for (int i = 0; i < columns.size(); i++) {
                Column column = columns.get(i);
                if (column.isVisible()) {
                    sheet.setColumnWidth(i, 100 * column.getWidth());
                    HSSFCell cell = row.createCell(i);
                    cell.setCellStyle(style);
                    HSSFRichTextString text = new HSSFRichTextString(column.getTitle());
                    cell.setCellValue(text);
                }
            }
            // 遍历集合数据，产生数据行
            for (int index = 0; index < dataList.size(); index++) {
                Object bean = dataList.get(index);
                row = sheet.createRow(index + 1);
                for (int i = 0; i < columns.size(); i++) {
                    Column column = columns.get(i);
                    if (column.isVisible()) {
                        HSSFCell cell = row.createCell(i);
                        cell.setCellStyle(style2);
                        String field = column.getField();
                        Object value = BeanConvertUtils.getProperty(bean, field);
                        if (value != null) {
                            String textValue = null;
                            // 判断值的类型后进行强制类型转换
                            Function<Object, String> function = column.getFunction();
                            if(function != null) {
                                textValue = function.apply(value);
                            }else if (value instanceof Number) {
                                cell.setCellValue(((Number)value).doubleValue());
                            } else if (value instanceof byte[]) {
                                // 有图片时，设置行高为60px;
                                row.setHeightInPoints(60);
                                // 设置图片所在列宽度为80px,注意这里单位的一个换算
                                sheet.setColumnWidth(i, (short)(35.7 * 80));
                                byte[] bsValue = (byte[])value;
                                HSSFClientAnchor anchor =
                                    new HSSFClientAnchor(0, 0, 1023, 255, (short)6, index, (short)6, index);
                                anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_DONT_RESIZE);
                                patriarch.createPicture(anchor,
                                    workbook.addPicture(bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));
                            } else if (value instanceof Date) {
                                textValue = DateUtils.formatDate((Date)value, FbConstant.DATETIME_FORMAT);
                            } else {
                                // 其它数据类型都当作字符串简单处理
                                textValue = value.toString();
                            }
                            if (textValue != null) {
                                HSSFRichTextString richString = new HSSFRichTextString(textValue);
                                richString.applyFont(font3);
                                cell.setCellValue(richString);
                            }
                        }
                    }
                }
            }
            return saveExcel(workbook, dir);
        } catch (Exception e) {
            log.error("", e);
            return null;
        }
    }
    
    /**
     * 用于多Sheet导出，只插入数据，不保存文件
     * @param workbook
     * @param title
     * @param dataList
     * @param columns
     */
    public static void exportExcel(HSSFWorkbook workbook, String title, List<?> dataList, List<Column> columns) {
        try {
            // 声明一个工作薄
            // 生成一个表格
            HSSFSheet sheet = workbook.createSheet(title);
            // 设置表格默认列宽度为15个字节
            sheet.setDefaultColumnWidth(20);
            // 生成一个样式
            HSSFCellStyle style = workbook.createCellStyle();
            // 生成一个字体
            HSSFFont font = workbook.createFont();

            font.setFontHeightInPoints((short)12);
            font.setBold(true);
            // 把字体应用到当前的样式
            style.setFont(font);
            // 生成并设置另一个样式
            HSSFCellStyle style2 = workbook.createCellStyle();
            // 生成另一个字体
            HSSFFont font2 = workbook.createFont();
            font2.setBold(false);
            // 把字体应用到当前的样式
            style2.setFont(font2);
            HSSFFont font3 = workbook.createFont();
            // 声明一个画图的顶级管理器
            HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
            // 产生表格标题行
            HSSFRow row = sheet.createRow(0);
            for (int i = 0; i < columns.size(); i++) {
                Column column = columns.get(i);
                if (column.isVisible()) {
                    sheet.setColumnWidth(i, 100 * column.getWidth());
                    HSSFCell cell = row.createCell(i);
                    cell.setCellStyle(style);
                    HSSFRichTextString text = new HSSFRichTextString(column.getTitle());
                    cell.setCellValue(text);
                }
            }
            // 遍历集合数据，产生数据行
            for (int index = 0; index < dataList.size(); index++) {
                Object bean = dataList.get(index);
                row = sheet.createRow(index + 1);
                for (int i = 0; i < columns.size(); i++) {
                    Column column = columns.get(i);
                    if (column.isVisible()) {
                        HSSFCell cell = row.createCell(i);
                        cell.setCellStyle(style2);
                        String field = column.getField();
                        Object value = BeanConvertUtils.getProperty(bean, field);
                        if (value != null) {
                            String textValue = null;
                            // 判断值的类型后进行强制类型转换
                            Function<Object, String> function = column.getFunction();
                            if(function != null) {
                                textValue = function.apply(value);
                            }else if (value instanceof Number) {
                                cell.setCellValue(((Number)value).doubleValue());
                            } else if (value instanceof byte[]) {
                                // 有图片时，设置行高为60px;
                                row.setHeightInPoints(60);
                                // 设置图片所在列宽度为80px,注意这里单位的一个换算
                                sheet.setColumnWidth(i, (short)(35.7 * 80));
                                byte[] bsValue = (byte[])value;
                                HSSFClientAnchor anchor =
                                    new HSSFClientAnchor(0, 0, 1023, 255, (short)6, index, (short)6, index);
                                anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_DONT_RESIZE);
                                patriarch.createPicture(anchor,
                                    workbook.addPicture(bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));
                            } else if (value instanceof Date) {
                                textValue = DateUtils.formatDate((Date)value, FbConstant.DATETIME_FORMAT);
                            } else {
                                // 其它数据类型都当作字符串简单处理
                                textValue = value.toString();
                            }
                            if (textValue != null) {
                                HSSFRichTextString richString = new HSSFRichTextString(textValue);
                                richString.applyFont(font3);
                                cell.setCellValue(richString);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
        	log.error("", e);
        }
    }
    
    /**
     * 保存excel文件
     * @param workbook
     * @param dir
     * @return
     */
    public static String saveExcel(HSSFWorkbook workbook, String dir) {
        try {
            File file = new File(dir);
            if (!file.exists()) {
                file.mkdirs();
            }
            String fileName = UUID.randomUUID().toString().replace("-", "");
            FileOutputStream downloadFile = new FileOutputStream(file.getAbsolutePath() + "/" + fileName);
            workbook.write(downloadFile);// 写出文件
            downloadFile.close();
            return fileName;
        } catch (Exception e) {
            log.error("", e);
            return null;
        }
    }
}
